Smart pointery

Po co są inteligentne wskaźniki?

Inteligentne wskaźniki to część nowoczesnego C++. Są one bezpieczniejsze w użyciu od zwykłych, a także same usuwają się z pamięci, a więc programista nie musi się tym martwić.

unique_ptr

Wskaźnik unikalny to najprostszy inteligentny wskaźnik. Może mieć maksymalnie jednego właściciela. Możemy go przesuwać za pomocą funkcji move().

#include <iostream>

using namespace std;

int main(){
    unique_ptr<int> wskaznik = make_unique<int>(15);

    cout << "Wartosc wskaznik: " << *wskaznik << endl;

    unique_ptr<int> wskaznik2 = move(wskaznik);

    // cout << "Wartosc wskaznik: " << *wskaznik << endl; - nie działa

    cout << "Wartosc wskaznik2: " << *wskaznik2 << endl;
}

W powyższym przykładzie wartość wskaźnika wskaznik będzie pusta. Dzieje się tak, ponieważ przesuneliśmy wskaźnik do wskaźnika wskaznik2, a unique_ptr może mieć tylko jednego właściciela.

shared_ptr

Wskaźnik współdzielony (shared pointer) to wskaźnik, który może mieć wielu właścicieli. Czyli wiele wskaźników może wskazywać na jedną wartość.

#include <iostream>

using namespace std;

int main()
{
    shared_ptr<string> wskaznik1 = make_shared<string>("hello world");

    shared_ptr<string> wskaznik2 = wskaznik1;

    cout << "Wartosc wskaznik1: " << *wskaznik1 << endl;
    cout << "Wartosc wskaznik2: " << *wskaznik2 << endl;
}

Tutaj oba wskaźniki przyjeły wartość "hello world".

Co więcej, możemy sprawdzić ile wskaźników wskazuje na daną wartość za pomocą metody use_count().

#include <iostream>

using namespace std;

int main()
{
    shared_ptr<string> wskaznik1 = make_shared<string>("hello world");

    shared_ptr<string> wskaznik2 = wskaznik1;

    cout << "Wartosc wskaznik1: " << *wskaznik1 << endl;
    cout << "Wartosc wskaznik2: " << *wskaznik2 << endl;

    cout << "Ilosc wskaznikow na ta wartosc: " << wskaznik1.use_count() << endl;
}

weak_ptr

Wskaźnik słaby (weak pointer) to najrzadziej używany z tych trzech wskaźników. Może on wskazywać tylko na wartość wskaźnika shared_ptr. Co ważne, nie staje się wtedy właścicielem (czyli use_count() się nie zwiększy). Może on jako jedyny z trzech wskaźników sprawdzać, czy dana wartość nadal istnieje (metoda expired()), a także samemu zmienić się w shared_ptr (metoda lock()).